<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js"><span id='global-property-'>/**
</span> * @ignore
 * enhanced base for model with sync
 * @author yiminghe@gmail.com
 */
KISSY.add(&quot;mvc/model&quot;, function (S, Base) {
    var blacklist = [
        &quot;idAttribute&quot;,
        &quot;destroyed&quot;,
        &quot;plugins&quot;,
        &quot;listeners&quot;,
        &quot;clientId&quot;,
        &quot;urlRoot&quot;,
        &quot;url&quot;,
        &quot;parse&quot;,
        &quot;sync&quot;
    ];

<span id='KISSY-MVC-Model'>    /**
</span>     * Model represent a data record.
     * @class KISSY.MVC.Model
     * @extends KISSY.Base
     */
   return Base.extend({
       initializer:function(){
           /*
            *Change should bubble to its collections
            */
           this.collections = {};
       },

<span id='KISSY-MVC-Model-method-addToCollection'>            /**
</span>             * Add current model instance to a specified collection.
             * @param {KISSY.MVC.Collection} c
             */
            addToCollection:function (c) {
                this.collections[S.stamp(c)] = c;
                this.addTarget(c);
            },
<span id='KISSY-MVC-Model-method-removeFromCollection'>            /**
</span>             * Remove current model instance from a specified collection.
             * @param {KISSY.MVC.Collection} c
             */
            removeFromCollection:function (c) {
                delete this.collections[S.stamp(c)];
                this.removeTarget(c);
            },

<span id='KISSY-MVC-Model-method-getId'>            /**
</span>             * Get current model 's id.
             */
            getId:function () {
                return this.get(this.get(&quot;idAttribute&quot;));
            },

<span id='KISSY-MVC-Model-method-setId'>            /**
</span>             * Set current model 's id.
             * @param id
             */
            'setId':function (id) {
                return this.set(this.get(&quot;idAttribute&quot;), id);
            },

            setInternal:function () {
                this.__isModified = 1;
                return this.callSuper.apply(this,arguments);
            },

<span id='KISSY-MVC-Model-method-isNew'>            /**
</span>             * whether it is newly created.
             * @return {Boolean}
             */
            isNew:function () {
                return !this.getId();
            },

<span id='KISSY-MVC-Model-method-isModified'>            /**
</span>             * whether has been modified since last save.
             * @return {Boolean}
             */
            isModified:function () {
                return !!(this.isNew() || this.__isModified);
            },

<span id='KISSY-MVC-Model-method-destroy'>            /**
</span>             * destroy this model and sync with server.
             * @param {Object} [opts] destroy config.
             * @param {Function} opts.success callback when action is done successfully.
             * @param {Function} opts.error callback when error occurs at action.
             * @param {Function} opts.complete callback when action is complete.
             * @chainable
             */
            destroy:function (opts) {
                var self = this;
                opts = opts || {};
                var success = opts.success;
<span id='global-method-success'>                /**
</span>                 * @ignore
                 */
                opts.success = function (resp) {
                    var lists = self.collections;
                    if (resp) {
                        var v = self.get(&quot;parse&quot;).call(self, resp);
                        if (v) {
                            self.set(v, opts);
                        }
                    }
                    for (var l in lists) {
                        lists[l].remove(self, opts);
                    }
                    self.fire(&quot;destroy&quot;);
                    success &amp;&amp; success.apply(this, arguments);
                };
                if (!self.isNew() &amp;&amp; opts['delete']) {
                    self.get(&quot;sync&quot;).call(self, self, 'delete', opts);
                } else {
                    opts.success();
                    if (opts.complete) {
                        opts.complete();
                    }
                }

                return self;
            },

<span id='KISSY-MVC-Model-method-load'>            /**
</span>             * Load model data from server.
             * @param {Object} opts Load config.
             * @param {Function} opts.success callback when action is done successfully.
             * @param {Function} opts.error callback when error occurs at action.
             * @param {Function} opts.complete callback when action is complete.
             * @chainable
             */
            load:function (opts) {
                var self = this;
                opts = opts || {};
                var success = opts.success;
<span id='global-method-success'>                /**
</span>                 * @ignore
                 */
                opts.success = function (resp) {
                    if (resp) {
                        var v = self.get(&quot;parse&quot;).call(self, resp);
                        if (v) {
                            self.set(v, opts);
                        }
                    }
                    self.__isModified = 0;
                    success &amp;&amp; success.apply(this, arguments);
                };
                self.get(&quot;sync&quot;).call(self, self, 'read', opts);
                return self;
            },

<span id='KISSY-MVC-Model-method-save'>            /**
</span>             * Save current model 's data to server using sync.
             * @param {Object} opts Save config.
             * @param {Function} opts.success callback when action is done successfully.
             * @param {Function} opts.error callback when error occurs at action.
             * @param {Function} opts.complete callback when action is complete.
             * @chainable
             */
            save:function (opts) {
                var self = this;
                opts = opts || {};
                var success = opts.success;
<span id='global-method-success'>                /**
</span>                 * @ignore
                 */
                opts.success = function (resp) {
                    if (resp) {
                        var v = self.get(&quot;parse&quot;).call(self, resp);
                        if (v) {
                            self.set(v, opts);
                        }
                    }
                    self.__isModified = 0;
                    success &amp;&amp; success.apply(this, arguments);
                };
                self.get(&quot;sync&quot;).call(self, self, self.isNew() ? 'create' : 'update', opts);
                return self;
            },

<span id='KISSY-MVC-Model-method-toJSON'>            /**
</span>             * Get json representation for current model.
             * @return {Object}
             */
            toJSON:function () {
                var ret = this.getAttrVals();
                S.each(blacklist, function (b) {
                    delete ret[b];
                });
                return ret;
            }

        }, {
            ATTRS:{
<span id='KISSY-MVC-Model-property-idAttribute'>                /**
</span>                 * Attribute name used to store id from server.
                 * Defaults to: &quot;id&quot;.
                 * @type {String}
                 */
                idAttribute:{
                    value:'id'
                },

<span id='KISSY-MVC-Model-property-clientId'>                /**
</span>                 * Generated client id.
                 * Default call S.guid()
                 * @type {Function}
                 */
                clientId:{
                    valueFn:function () {
                        return S.guid(&quot;mvc-client&quot;);
                    }
                },
<span id='KISSY-MVC-Model-property-url'>                /**
</span>                 * Called to get url for delete/edit/new current model.
                 * Defaults to: collection.url+&quot;/&quot;+mode.id
                 * @type {Function}
                 */
                url:{
                    value:url
                },
<span id='KISSY-MVC-Model-property-urlRoot'>                /**
</span>                 * If current model does not belong to any collection.
                 * Use this attribute value as collection.url in {@link KISSY.MVC.Model#url}
                 * @type {String}
                 */
                urlRoot:{
                    value:&quot;&quot;
                },
<span id='KISSY-MVC-Model-property-sync'>                /**
</span>                 * Sync model data with server.
                 * Default to call {@link KISSY.MVC#sync}
                 * @type {Function}
                 */
                sync:{
                    value:function () {
                        S.require(&quot;mvc&quot;).sync.apply(this, arguments);
                    }
                },
<span id='KISSY-MVC-Model-property-parse'>                /**
</span>                 * parse json from server to get attr/value pairs.
                 * Default to return raw data from server.
                 * @type {Function}
                 */
                parse:{
                    value:function (resp) {
                        return resp;
                    }
                }
            }
        });

    function getUrl(o) {
        var u;
        if (o &amp;&amp; (u = o.get(&quot;url&quot;))) {
            if (typeof u == 'string') {
                return u;
            }
            return u.call(o);
        }
        return u;
    }

    function url() {
        var c,
            cv,
            collections = this.collections;
        for (c in collections) {
            if (collections.hasOwnProperty(c)) {
                cv = collections[c];
                break;
            }
        }
        var base = getUrl(cv) || this.get(&quot;urlRoot&quot;);

        if (this.isNew()) {
            return base;
        }

        base = base + (base.charAt(base.length - 1) == '/' ? '' : '/');
        return base + encodeURIComponent(this.getId()) + &quot;/&quot;;
    }
}, {
    requires:['base']
});</pre>
</body>
</html>
